package com.ibeeking.found.cop.cp.rest.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ibeeking.found.common.config.prop.FileOssProp;
import com.ibeeking.found.common.constants.DefaultPathConstant;
import com.ibeeking.found.common.enums.EmployeeStatusEnum;
import com.ibeeking.found.common.enums.SexEnum;
import com.ibeeking.found.common.utils.UrlUtils;
import com.ibeeking.found.cop.cp.rest.config.prop.EmployeeConfigProp;
import com.ibeeking.found.cop.cp.rest.service.ICopDepartmentService;
import com.ibeeking.found.cop.cp.rest.service.ICopEmployeeService;
import com.ibeeking.found.cop.service.common.bo.CopEmployeeBO;
import com.ibeeking.found.cop.service.common.constants.RedisKeyConstant;
import com.ibeeking.found.cop.service.common.dos.CopDepartmentDO;
import com.ibeeking.found.cop.service.common.dos.CopEmployeeDO;
import com.ibeeking.found.cop.service.common.query.CopEmployeePageQuery;
import com.ibeeking.found.cop.service.common.query.CopEmployeeQuery;
import com.ibeeking.found.cop.service.common.vo.CopDepartmentVO;
import com.ibeeking.found.cop.service.common.vo.CopEmployeeVO;
import com.ibeeking.found.cop.service.mapper.CopDepartmentMapper;
import com.ibeeking.found.cop.service.mapper.CopEmployeeMapper;
import com.ibeeking.gmc.global.api.feign.GlobalDictFeignClient;
import com.ibeeking.nematos.core.utils.SpringBeanUtil;
import com.ibeeking.nematos.exception.BusinessException;
import com.ibeeking.nematos.redis.annotation.CacheEvict;
import com.ibeeking.nematos.redis.utils.RedisUtils;
import com.ibeeking.nematos.utils.bean.BeanUtil;
import com.ibeeking.nematos.utils.data.Collections3;
import com.ibeeking.nematos.utils.data.TreeFastUtils;
import com.ibeeking.nematos.utils.json.JsonUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
 * @ClassName CopDepartmentServiceImpl
 * @Description
 * @Author ibeeking
 * @Date 2021-01-27 18:50
 **/
@Service
public class CopEmployeeServiceImpl extends ServiceImpl<CopEmployeeMapper, CopEmployeeDO> implements ICopEmployeeService {

    @Resource
    private CopEmployeeMapper copEmployeeMapper;

    @Resource
    private CopDepartmentMapper copDepartmentMapper;

    @Resource
    private ICopDepartmentService copDepartmentServiceImpl;

    @Resource
    private GlobalDictFeignClient globalDictFeignClient;

    @Resource
    private EmployeeConfigProp configProp;

    @Resource
    private FileOssProp fileOssProp;

    @Resource
    private RedisUtils redisUtils;

    @Override
    public List<CopEmployeeVO> list(CopEmployeeQuery query){
        List<CopDepartmentDO> copDepartmentDOS = copDepartmentMapper.selectList(new LambdaQueryWrapper<CopDepartmentDO>());
        Long mainDepartmentId = query.getMainDepartmentId();
        List<Long> allMainDepartmentIds = new ArrayList<>();
        if(mainDepartmentId!=null){
            allMainDepartmentIds.add(mainDepartmentId);
           if(Collections3.isNotEmpty(copDepartmentDOS)){
               List<CopDepartmentVO> allCopDepartmentTrees = JsonUtils.jsonToList(copDepartmentDOS, CopDepartmentVO.class);
               List<Long> mainDepartmentIds= new ArrayList<>();
               mainDepartmentIds.add(mainDepartmentId);
               List<Long> result = new ArrayList<>();
               TreeFastUtils.selectLongCidByPid(result, allCopDepartmentTrees, mainDepartmentIds);
               allMainDepartmentIds.addAll(result);
           }
        }

        LambdaQueryWrapper<CopEmployeeDO> queryWrapper = new LambdaQueryWrapper<>(CopEmployeeDO.class)
                .eq(query.getId()!= null, CopEmployeeDO::getId, query.getId())
                .eq(StringUtils.isNotEmpty(query.getEmployeeCode()), CopEmployeeDO::getEmployeeCode, query.getEmployeeCode())
                .eq(query.getGender() != null, CopEmployeeDO::getGender, query.getGender())
                .eq(query.getStatus() != null, CopEmployeeDO::getStatus, query.getStatus())
                .in(Collections3.isNotEmpty(allMainDepartmentIds), CopEmployeeDO::getMainDepartmentId, allMainDepartmentIds)
                .like(StringUtils.isNotEmpty(query.getEmployeeName()), CopEmployeeDO::getEmployeeName, query.getEmployeeName())
                .like(StringUtils.isNotEmpty(query.getNickName()), CopEmployeeDO::getNickName, query.getNickName())
                .orderByDesc(CopEmployeeDO::getCreateTime);
        List<CopEmployeeDO> copEmployeeDOS = copEmployeeMapper.selectList(queryWrapper);

        Map<Long, String> copDepartmentNameCnMaps = Collections3.isNotEmpty(copDepartmentDOS)?copDepartmentDOS.parallelStream().collect(Collectors.toMap(CopDepartmentDO::getId, CopDepartmentDO::getName, (o, n) -> o)):null;

        List<CopEmployeeVO> copEmployeeVOS = copEmployeeDOS.stream().map(d->{
            CopEmployeeVO copEmployeeVO = BeanUtil.convertBean(d, CopEmployeeVO.class);
            copEmployeeVO.setGenderDesc(SexEnum.getDescByCode(d.getGender()));
            copEmployeeVO.setMainDepartmentName(copDepartmentNameCnMaps!=null?copDepartmentNameCnMaps.get(d.getMainDepartmentId()):null);

            if(StringUtils.isNotEmpty(d.getNickName())){
                String employeeNameCnEn = (d.getEmployeeName()).concat("(").concat(d.getNickName()).concat(")");
                copEmployeeVO.setEmployeeNameAndNick(employeeNameCnEn);
            }else{
                copEmployeeVO.setEmployeeNameAndNick(d.getEmployeeName());
            }
            copEmployeeVO.setStatusDesc(EmployeeStatusEnum.getDescByCode(d.getStatus()));
            return copEmployeeVO;
        }).collect(Collectors.toList());
        return copEmployeeVOS;
    }

    @Override
    public Page<CopEmployeeVO> pageList(CopEmployeePageQuery pageQuery){
        List<CopDepartmentDO> copDepartmentDOS = copDepartmentMapper.selectList(new LambdaQueryWrapper<CopDepartmentDO>());
        Long mainDepartmentId = pageQuery.getMainDepartmentId();
        List<Long> allMainDepartmentIds = new ArrayList<>();
        if(mainDepartmentId!=null){
            allMainDepartmentIds.add(mainDepartmentId);
            if(Collections3.isNotEmpty(copDepartmentDOS)){
                List<CopDepartmentVO> allCopDepartmentTrees = JsonUtils.jsonToList(copDepartmentDOS, CopDepartmentVO.class);
                List<Long> mainDepartmentIds= new ArrayList<>();
                mainDepartmentIds.add(mainDepartmentId);
                List<Long> result = new ArrayList<>();
                TreeFastUtils.selectLongCidByPid(result, allCopDepartmentTrees, mainDepartmentIds);
                allMainDepartmentIds.addAll(result);
            }
        }
        LambdaQueryWrapper<CopEmployeeDO> queryWrapper = new LambdaQueryWrapper<>(CopEmployeeDO.class)
                .eq(pageQuery.getId()!= null, CopEmployeeDO::getId, pageQuery.getId())
                .eq(StringUtils.isNotEmpty(pageQuery.getEmployeeCode()), CopEmployeeDO::getEmployeeCode, pageQuery.getEmployeeCode())
                .eq(pageQuery.getGender() != null, CopEmployeeDO::getGender, pageQuery.getGender())
                .eq(pageQuery.getStatus() != null, CopEmployeeDO::getStatus, pageQuery.getStatus())
                .in(Collections3.isNotEmpty(allMainDepartmentIds), CopEmployeeDO::getMainDepartmentId, allMainDepartmentIds)
                .like(StringUtils.isNotEmpty(pageQuery.getEmployeeName()), CopEmployeeDO::getEmployeeName, pageQuery.getEmployeeName())
                .like(StringUtils.isNotEmpty(pageQuery.getNickName()), CopEmployeeDO::getNickName, pageQuery.getNickName())
                .orderByDesc(CopEmployeeDO::getCreateTime);
        Page<CopEmployeeDO> copEmployeeDOPages = copEmployeeMapper.selectPage(new Page<CopEmployeeDO>(pageQuery.getPageNum(), pageQuery.getPageSize()), queryWrapper);
        List<CopEmployeeDO> copEmployeeDOS = copEmployeeDOPages.getRecords();
        Page<CopEmployeeVO> copEmployeeVOPages = BeanUtil.convertPage(copEmployeeDOPages, CopEmployeeVO.class);

        Map<Long, String> copDepartmentNameCnMaps = Collections3.isNotEmpty(copDepartmentDOS)?copDepartmentDOS.parallelStream().collect(Collectors.toMap(CopDepartmentDO::getId, CopDepartmentDO::getName, (o, n) -> o)):null;

        List<CopEmployeeVO> copEmployeeVOS = copEmployeeDOS.stream().map(d->{
            CopEmployeeVO copEmployeeVO = BeanUtil.convertBean(d, CopEmployeeVO.class);
            copEmployeeVO.setGenderDesc(SexEnum.getDescByCode(d.getGender()));
            copEmployeeVO.setMainDepartmentName(copDepartmentNameCnMaps!=null?copDepartmentNameCnMaps.get(d.getMainDepartmentId()):null);

            if(StringUtils.isNotEmpty(d.getNickName())){
                String employeeNameCnEn = (d.getEmployeeName()).concat("(").concat(d.getNickName()).concat(")");
                copEmployeeVO.setEmployeeNameAndNick(employeeNameCnEn);
            }else{
                copEmployeeVO.setEmployeeNameAndNick(d.getEmployeeName());
            }
            copEmployeeVO.setStatusDesc(EmployeeStatusEnum.getDescByCode(d.getStatus()));
            return copEmployeeVO;
        }).collect(Collectors.toList());
        copEmployeeVOPages.setRecords(copEmployeeVOS);
        return copEmployeeVOPages;
    }

    @Override
    public Page<CopEmployeeVO> pageListWithSubDepartment(CopEmployeePageQuery pageQuery){
        if(pageQuery.getMainDepartmentId() == null){
            throw new BusinessException("部门ID不能为空");
        }
        List<Long> mainDepartmentIds = copDepartmentServiceImpl.getDepartmentIdWithSubByParentId(pageQuery.getMainDepartmentId());
        LambdaQueryWrapper<CopEmployeeDO> queryWrapper = new LambdaQueryWrapper<>(CopEmployeeDO.class)
                .eq(pageQuery.getId()!= null, CopEmployeeDO::getId, pageQuery.getId())
                .eq(StringUtils.isNotEmpty(pageQuery.getEmployeeCode()), CopEmployeeDO::getEmployeeCode, pageQuery.getEmployeeCode())
                .eq(pageQuery.getGender() != null, CopEmployeeDO::getGender, pageQuery.getGender())
                .eq(pageQuery.getStatus() != null, CopEmployeeDO::getStatus, pageQuery.getStatus())
                .in(Collections3.isNotEmpty(mainDepartmentIds), CopEmployeeDO::getMainDepartmentId, mainDepartmentIds)
                .like(StringUtils.isNotEmpty(pageQuery.getEmployeeName()), CopEmployeeDO::getEmployeeName, pageQuery.getEmployeeName())
                .like(StringUtils.isNotEmpty(pageQuery.getNickName()), CopEmployeeDO::getNickName, pageQuery.getNickName())
                .orderByDesc(CopEmployeeDO::getCreateTime);
        Page<CopEmployeeDO> copEmployeeDOPages = copEmployeeMapper.selectPage(new Page<CopEmployeeDO>(pageQuery.getPageNum(), pageQuery.getPageSize()), queryWrapper);
        List<CopEmployeeDO> copEmployeeDOS = copEmployeeDOPages.getRecords();
        Page<CopEmployeeVO> copEmployeeVOPages = BeanUtil.convertPage(copEmployeeDOPages, CopEmployeeVO.class);

        List<CopDepartmentDO> copDepartmentDOS = copDepartmentMapper.selectList(new LambdaQueryWrapper<CopDepartmentDO>());
        Map<Long, String> copDepartmentNameCnMaps = copDepartmentDOS.parallelStream().collect(Collectors.toMap(CopDepartmentDO::getId, CopDepartmentDO::getName, (o, n) -> o));

        List<CopEmployeeVO> copEmployeeVOS = copEmployeeDOS.stream().map(d->{
            CopEmployeeVO copEmployeeVO = BeanUtil.convertBean(d, CopEmployeeVO.class);
            copEmployeeVO.setGenderDesc(SexEnum.getDescByCode(d.getGender()));
            copEmployeeVO.setMainDepartmentName(copDepartmentNameCnMaps.get(d.getMainDepartmentId()));

            if(StringUtils.isNotEmpty(d.getNickName())){
                String employeeNameCnEn = (d.getEmployeeName()).concat("(").concat(d.getNickName()).concat(")");
                copEmployeeVO.setEmployeeNameAndNick(employeeNameCnEn);
            }else{
                copEmployeeVO.setEmployeeNameAndNick(d.getEmployeeName());
            }
            copEmployeeVO.setStatusDesc(EmployeeStatusEnum.getDescByCode(d.getStatus()));
            return copEmployeeVO;
        }).collect(Collectors.toList());
        copEmployeeVOPages.setRecords(copEmployeeVOS);
        return copEmployeeVOPages;
    }

    @Override
    public List<CopEmployeeVO> listByDepartmentId(Long departmentId){

        LambdaQueryWrapper<CopEmployeeDO> queryWrapper = new LambdaQueryWrapper<>(CopEmployeeDO.class);
        queryWrapper.eq(CopEmployeeDO::getMainDepartmentId, departmentId);

        List<CopEmployeeDO> copEmployeeDOS = copEmployeeMapper.selectList(queryWrapper);

        List<CopDepartmentDO> copDepartmentDOS = copDepartmentMapper.selectList(new LambdaQueryWrapper<CopDepartmentDO>());
        Map<Long, String> copDepartmentNameCnMaps = copDepartmentDOS.parallelStream().collect(Collectors.toMap(CopDepartmentDO::getId, CopDepartmentDO::getName, (o, n) -> o));

        List<CopEmployeeVO> copEmployeeVOS = copEmployeeDOS.stream().map(d->{
            CopEmployeeVO copEmployeeVO = BeanUtil.convertBean(d, CopEmployeeVO.class);
            copEmployeeVO.setGenderDesc(SexEnum.getDescByCode(d.getGender()));
            copEmployeeVO.setMainDepartmentName(copDepartmentNameCnMaps.get(d.getMainDepartmentId()));

            if(StringUtils.isNotEmpty(d.getNickName())){
                String employeeNameCnEn = (d.getEmployeeName()).concat("(").concat(d.getNickName()).concat(")");
                copEmployeeVO.setEmployeeNameAndNick(employeeNameCnEn);
            }else{
                copEmployeeVO.setEmployeeNameAndNick(d.getEmployeeName());
            }
            copEmployeeVO.setStatusDesc(EmployeeStatusEnum.getDescByCode(d.getStatus()));
            return copEmployeeVO;
        }).collect(Collectors.toList());
        return copEmployeeVOS;
    }

    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(cacheName = RedisKeyConstant.EMPLOYEE_PREFIX, key = "#copEmployeeDO.id")
    @Override
    public Boolean updateEmployeeById(CopEmployeeDO copEmployeeDO) {
        if (copEmployeeDO == null) {
            return false;
        }
        return copEmployeeMapper.updateById(copEmployeeDO) > 0;
    }

    @Override
    public CopEmployeeVO view(Long id){
        CopEmployeeDO copEmployeeDO = copEmployeeMapper.selectById(id);
        if(copEmployeeDO == null) return null;

        List<CopDepartmentDO> copDepartmentDOS = copDepartmentMapper.selectList(new LambdaQueryWrapper<CopDepartmentDO>());
        Map<Long, String> copDepartmentNameCnMaps = copDepartmentDOS.parallelStream().collect(Collectors.toMap(CopDepartmentDO::getId, CopDepartmentDO::getName, (o, n) -> o));

        CopEmployeeVO copEmployeeVO = BeanUtil.convertBean(copEmployeeDO, CopEmployeeVO.class);
        copEmployeeVO.setGenderDesc(SexEnum.getDescByCode(copEmployeeVO.getGender()));
        copEmployeeVO.setMainDepartmentName(copDepartmentNameCnMaps.get(copEmployeeVO.getMainDepartmentId()));

        if(StringUtils.isNotEmpty(copEmployeeVO.getNickName())){
            String employeeNameCnEn = (copEmployeeVO.getEmployeeName()).concat("(").concat(copEmployeeVO.getNickName()).concat(")");
            copEmployeeVO.setEmployeeNameAndNick(employeeNameCnEn);
        }else{
            copEmployeeVO.setEmployeeNameAndNick(copEmployeeVO.getEmployeeName());
        }
        copEmployeeVO.setStatusDesc(EmployeeStatusEnum.getDescByCode(copEmployeeVO.getStatus()));

        return copEmployeeVO;
    }

    @Override
    public CopEmployeeBO queryByEmployeeCode(String employeeCode){
        CopEmployeeDO copEmployeeDO = copEmployeeMapper.selectOne(new LambdaQueryWrapper<CopEmployeeDO>()
                .eq(StringUtils.isNotEmpty(employeeCode), CopEmployeeDO::getEmployeeCode, employeeCode)
                .eq(CopEmployeeDO::getStatus, EmployeeStatusEnum.IS_ACTIVED)
        );
        if(copEmployeeDO == null) return null;
        CopEmployeeBO copEmployeeBO = BeanUtil.convertBean(copEmployeeDO, CopEmployeeBO.class);
        return copEmployeeBO;
    }

    @Override
    public CopEmployeeBO queryByMobile(String mobile){
        CopEmployeeDO copEmployeeDO = copEmployeeMapper.selectOne(new LambdaQueryWrapper<CopEmployeeDO>()
                .eq(StringUtils.isNotEmpty(mobile), CopEmployeeDO::getMobile, mobile)
                .eq(CopEmployeeDO::getStatus, EmployeeStatusEnum.IS_ACTIVED)
        );
        if(copEmployeeDO == null) return null;
        CopEmployeeBO copEmployeeBO = BeanUtil.convertBean(copEmployeeDO, CopEmployeeBO.class);
        return copEmployeeBO;
    }

    @Override
    public CopEmployeeBO selectById(Long id) {
        if (id == null) {
            return null;
        }
        CopEmployeeDO memberInfoDO = copEmployeeMapper.selectById(id);
        if(StringUtils.isEmpty(memberInfoDO.getAvatar()))
            memberInfoDO.setAvatar(DefaultPathConstant.DEFAULT_USER_HEAD_IMAGE);
        memberInfoDO.setAvatar(UrlUtils.addUrlDomainName(fileOssProp.getHost(),memberInfoDO.getAvatar()));
        return BeanUtil.convertBeanByJson(memberInfoDO, CopEmployeeBO.class);
    }

    private static ICopEmployeeService getBean() {
        return SpringBeanUtil.getBean(ICopEmployeeService.class);
    }

}
